package cn.microven.mindmap.oprations;

import cn.microven.mindmap.components.part.MapPart;
import cn.microven.mindmap.components.line.MapLine;
import cn.microven.mindmap.components.node.NodeInformation;
import cn.microven.mindmap.components.node.RectangleNode;
import cn.microven.mindmap.components.part.BothSideMapPart;
import cn.microven.mindmap.components.part.LeftMapPart;
import cn.microven.mindmap.components.part.Part;
import cn.microven.mindmap.components.part.RightMapPart;
import javafx.collections.ObservableList;
import javafx.scene.paint.Color;
import javafx.util.Pair;

import java.io.*;
import java.util.ArrayList;
import java.util.Vector;

public class FileOperation {
    //对于两侧布局的思维导图，中心结点的子节点需考虑分布在左侧还是右侧，分情况递归恢复
    private static void restoreMap(NodeInformation root, BothSideMapPart bmp) {
        ArrayList<NodeInformation> leaves = root.getLeaves();
        for(NodeInformation leaf : leaves) {//根据子节点的布局类型，分别恢复左右两侧布局
            if(leaf.getMapType().equals("LeftMapPart")) {
                LeftMapPart node = new LeftMapPart(new RectangleNode());
                //恢复当前新建结点信息为leaf中存储的信息
                restoreData(leaf, node);
                bmp.addLeftLeaf(node);
                restoreLeftPart(leaf, node);
            }
            else {
                RightMapPart node = new RightMapPart(new RectangleNode());
                //恢复当前新建结点信息为leaf中存储的信息
                restoreData(leaf, node);
                bmp.addRightLeaf(node);
                restoreRightPart(leaf, node);
            }
        }
    }

    //恢复左侧布局
    private static void restoreLeftPart(NodeInformation parent, LeftMapPart lmp) {
        ArrayList<NodeInformation> leaves = parent.getLeaves();
        for(NodeInformation leaf : leaves) {
            LeftMapPart node = new LeftMapPart(new RectangleNode());
            //恢复当前新建结点信息为leaf中存储的信息
            restoreData(leaf, node);
            lmp.addLeaf(node);
            restoreLeftPart(leaf, node);
        }
    }

    //恢复右侧布局
    private static void restoreRightPart(NodeInformation parent, RightMapPart rmp) {
        ArrayList<NodeInformation> leaves = parent.getLeaves();
        for(NodeInformation leaf : leaves) {
            RightMapPart node = new RightMapPart(new RectangleNode());
            //恢复当前新建结点信息为leaf中存储的信息
            restoreData(leaf, node);
            rmp.addLeaf(node);
            restoreRightPart(leaf, node);
        }
    }

    //将保存在NodeInformation中的信息恢复到思维导图结点Part中
    private static void restoreData(NodeInformation node, Part mp) {
        mp.getRoot().setLevel(node.getLevel());
        mp.getRoot().setShapeColor(new Color(node.getR1(), node.getG1(), node.getB1(), 1));
        mp.getRoot().setFontColor(new Color(node.getR2(), node.getG2(), node.getB2(), 1));
        mp.getRoot().getNodeShape().setStroke(new Color(node.getR3(), node.getG3(), node.getB3(), 1));
        mp.getRoot().setText(node.getText());
        mp.getRoot().getLabel().setBold(node.isBold());
        mp.getRoot().getLabel().setItalic(node.isItalic());
        mp.getRoot().getLabel().setFontSize(node.getFontSize());
        mp.getRoot().getLabel().setFontFamily(node.getFontFamily());
        mp.getRoot().setRadius(node.getRadius());
    }

    //遍历整个思维导图，保存每个结点信息以及层次结构
    private static void storeMap(NodeInformation parent, Part mp) {
        if(mp.getType().equals("BothSideMapPart")){
            Vector<Pair<MapLine, Part>> leaves = ((BothSideMapPart)mp).getBothSideLeaves();
            for(Pair<MapLine, Part> leaf : leaves) {
                NodeInformation node = new NodeInformation();
                storeData(node, leaf.getValue());
                parent.getLeaves().add(node);
                storeMap(node, leaf.getValue());
            }
        }
        else{
            ObservableList<Pair<MapLine, Part>> leaves = ((MapPart)mp).getLeaves();
            for(Pair<MapLine, Part> leaf : leaves) {
                NodeInformation node = new NodeInformation();
                storeData(node, leaf.getValue());
                parent.getLeaves().add(node);
                storeMap(node, leaf.getValue());
            }
        }
    }

    //将思维导图结点Part中的数据存储到NodeInformation中
    private static void storeData(NodeInformation node, Part mp) {
        node.setLevel(mp.getRoot().getLevel());
        node.setText(mp.getRoot().getText());
        Color color1 = mp.getRoot().getShapeColor(), color2 = mp.getRoot().getFontColor(), color3 = (Color)mp.getRoot().getNodeShape().getStroke();
        node.setNodeColor(color1.getRed(), color1.getGreen(), color1.getBlue());
        node.setFontColor(color2.getRed(), color2.getGreen(), color2.getBlue());
        node.setEdgeColor(color3.getRed(), color3.getGreen(), color3.getBlue());
        node.setMapType(mp.getType());
        node.setBold(mp.getRoot().getLabel().isBold());
        node.setItalic(mp.getRoot().getLabel().isItalic());
        node.setFontSize(mp.getRoot().getLabel().getFontSize());
        node.setFontFamily(mp.getRoot().getLabel().getFontFamily());
        node.setRadius(mp.getRoot().getRadius());
    }

    public static BothSideMapPart readFile(String fileName) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName));
        Object obj = ois.readObject();
        NodeInformation node = (NodeInformation) obj;
        ois.close();

        //根节点单独恢复，子节点通过递归恢复
        BothSideMapPart mp = new BothSideMapPart(new RectangleNode());
        restoreData(node, mp);
        restoreMap(node, mp);
        return mp;
    }

    public static void writeFile(Part mp, String fileName) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName));
        NodeInformation nodeInfo = new NodeInformation();

        //根节点单独保存，子节点通过递归保存
        storeData(nodeInfo, mp);
        storeMap(nodeInfo, mp);

        oos.writeObject(nodeInfo);
        oos.close();
    }
}
